#pragma once
#include <lcir/ADT/IList.h>
#include <lcir/ADT/OwningRefVector.h>
#include <lcir/IR/Prototype.h>
#include <lcir/IR/Type.h>
#include <lcir/IR/Value.h>

#include <functional>
#include <iterator>
#include <memory>
#include <vector>
namespace lcir {
class Expression;
class LambdaProto;
class LambdaType;
class LambdaBase {
  friend class Expression;
  IList<Expression> exprs;
  std::unique_ptr<LambdaProto> proto;
  std::string name = "lambda";
  OwningRefVector<Value> arguments;

protected:
  LambdaBase() = default;

public:
  using exprList = IList<Expression>;
  exprList &getSubList() { return exprs; }
  exprList &getExprs() { return exprs; }
  const exprList &getExprs() const { return exprs; }
  std::vector<Value *> getArgs() const;

  // 返回插入的expr的指针
  Expression *insertExpr(Expression *insertPoint,
                         std::unique_ptr<Expression> expr);
  Expression *insertExprAfter(Expression *insertPoint,
                              std::unique_ptr<Expression> expr);
  Expression *pushBackExpr(std::unique_ptr<Expression> expr);
  Expression *pushFrontExpr(std::unique_ptr<Expression> expr);
  
  exprList::iterator end();
  exprList::iterator begin();
  exprList::constIterator end() const;
  exprList::constIterator begin() const;

  void addArgument(std::unique_ptr<Value> val);

  // void walk(std::function<void(const Expression* expr)> callback, bool
  // isBackWard = false) const; void walk(std::function<void(Expression* expr)>
  // callback, bool isBackWard = false);

  LambdaBase(LambdaBase &&other) = delete;
  LambdaBase &operator=(LambdaBase &&other) = delete;
  LambdaBase(const LambdaBase &other) = delete;
  LambdaBase &operator=(const LambdaBase &other) = delete;
  ~LambdaBase() = default;

};

} // namespace lcir